package com.hehao.java_basic.generic;

import lombok.Data;
import org.junit.Test;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * @author Damon
 * @date 2022/08/16/21:50
 * 泛型类、泛型方法
 */
@Data
public class GenericDemo {
    //1.泛型类
    //2.自定义泛型方法，不受自定义泛型类的影响
    public <E> List<E> transferToList(E[] arr) {
        List<E> list = new ArrayList<>();
        Arrays.stream(arr).forEach(list::add);
        return list;
    }

    /**
     *
     * @param <T> 声明一个泛型T 返回值前的<T>声明此方法持有一个类型T，声明此方法为泛型方法
     * @param object 创建泛型T的对象
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public <T> T getObject(Class<T> object) throws InstantiationException, IllegalAccessException {
        return object.newInstance();
    }

    /**
     * 测试自定义泛型方法getObject
     */
    @Test
    public void testGenericMethod() throws Exception {
        GenericDemo genericDemo = new GenericDemo();
        //Menu object = (Menu)genericDemo.getObject(Class.forName("com.hehao.demo.springDemo.springBoot.entity.Menu"));
        //Integer id = object.getId();
        //System.out.println(id);

    }


    /**
     * 测试自定义泛型方法transferToList
     */
    @Test
    public void testDefinedGeneric() {
        Integer[] arr = new Integer[]{1, 2, 3, 4};
        System.out.println(transferToList(arr));
    }


    /**
     * 泛型的上下限方法应用Demo
     * @param elements
     * @param <E>
     * @return
     */
    private <E extends Comparable<? super E>> E max(List<? extends E> elements){
        if (elements ==null) {
            return null;
        }
        Iterator<? extends E> iterator = elements.iterator();
        E result = iterator.next();
        while (iterator.hasNext()) {
            E next = iterator.next();
            if (next.compareTo(result)>0) {
                result = next;
            }
        }
        return result;
    }

    /**
     * 泛型多继承Demo
     * tips：这里面extends最多只能有一个类，其余的都应是接口
     */
    public interface GenericA{
    }
    @Data
    public static class GenericB{
    }
    public interface GenericC{
    }
    private static <T extends GenericB & GenericA &GenericC> void testGeneric(T t) {
    }

    /**
     * 测试泛型擦除Demo
     */
    @Test
    public void testGenericErasure() throws Exception {
        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("abc");

        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(123);
        //always true
        System.out.println(list1.getClass() == list2.getClass());
        ArrayList<String> list = new ArrayList<String>();
        list.add("sdfdsv");
        list.getClass().getMethod("add",Object.class).invoke(list,1);
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }


    public class GenericType<T> {
        private T data;

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }
    }

    /**
     * 获取泛型参数类型
     */
    @Test
    public void testGenericType() {
        GenericType<String> genericType = new GenericType<String>() {};
        Type superclass = genericType.getClass().getGenericSuperclass();
        //getActualTypeArguments 返回确切的泛型参数, 如Map<String, Integer>返回[String, Integer]
        Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
        System.out.println(type);//class java.lang.String
    }

    public static void main(String[] args) throws Exception {

    }
}
